package com.joysuch.wwyt.api.mh.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.joysuch.wwyt.api.mh.entity.MhPlatform;
import com.joysuch.wwyt.api.mh.entity.MhPlatformField;
import com.joysuch.wwyt.api.mh.entity.MhPlatformPoint;
import com.joysuch.wwyt.api.mh.entity.MonitorPointAPIData;
import com.joysuch.wwyt.api.mh.enums.MonitPointFieldDataType;
import com.joysuch.wwyt.api.mh.repository.MhPlatformDao;
import com.joysuch.wwyt.api.mh.repository.MhPlatformFieldDao;
import com.joysuch.wwyt.api.mh.repository.MhPlatformPointDao;
import com.joysuch.wwyt.api.mh.repository.MonitorPointDataAPIRepository;
import com.joysuch.wwyt.api.mh.service.MhPlatformSocketService;
import com.joysuch.wwyt.api.mh.socket.MhWebSocketClientInstance;
import com.joysuch.wwyt.core.common.util.MhAesUtil;
import com.joysuch.wwyt.core.entity.BaseTypeGroupItem;
import com.joysuch.wwyt.core.repository.BaseTypeGroupItemDao;
import com.joysuch.wwyt.core.security.ShiroUser;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.mh.repository.MhMonitoringPointDao;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.PreDestroy;
import javax.transaction.Transactional;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Transactional
@Slf4j
public class MhPlatformSocketServiceImpl implements MhPlatformSocketService {


    @Autowired
    private MhMonitoringPointDao mhMonitoringPointDao;
    @Autowired
    private MhPlatformDao mhPlatformDao;
    @Autowired
    private MhPlatformPointDao mhPlatformPointDao;
    @Autowired
    private MhPlatformFieldDao mhPlatformFieldDao;
    @Autowired
    private MonitorPointDataAPIRepository monitorPointDataAPIDao;
    @Autowired
    private BaseTypeGroupItemDao baseTypeGroupItemDao;


    private static final ScheduledThreadPoolExecutor taskScheduler = new ScheduledThreadPoolExecutor(5, r -> {
        Thread thread = new Thread(r, "MhPoint transfer worker");
        thread.setDaemon(true);
        return thread;
    });

    /**
     * 接入平台数据
     *
     * @return
     */
    @Override
    public void transferMhPointBySocket(Long platformId) {
        MhPlatform platform = mhPlatformDao.findById(platformId).get();
        if (platform.getFrequency() == null || platform.getFrequency() <= 0) {
            return;
        }
        ScheduledFuture<?> scheduledFuture = taskScheduler.scheduleAtFixedRate(() -> {
            log.info("监测点数据接入(Socket):Start..................");
            ShiroUser user = new ShiroUser();
            user.setTenentId(platform.getTenentId());
            //取的不定，两个都塞值
            user.setDepartCode(platform.getOrgCode().substring(0, 7));
            user.setCompanyCode(platform.getOrgCode().substring(0, 7));
            Context.setCurrentUser(user);
            List<MhPlatformPoint> pointList = mhPlatformPointDao.findByPlatformIdAndSwitchState(platform.getId(), 1);
            log.info("监测点数据接入(Socket):监测点size{}" + pointList.size());
            if (CollectionUtils.isEmpty(pointList)) return;
            //组装发送所需数据
            String socketMessage = getSocketMessage(platform, pointList);
            log.info("+++++++++++++++ getSocketMessage " + socketMessage + "++++++++++++++++++++");
            if (StringUtils.isNotBlank(platform.getUrl())) {
                String[] ipPort = platform.getUrl().trim().split(":");
                if (StringUtils.isEmpty(ipPort[0]) || ipPort.length < 2) {
                    log.info("监测点数据接入(Socket):url格式必须为IP:端口");
                    return;
                }
                //输送数据
                transforDataBySocket(socketMessage, ipPort[0], Integer.valueOf(ipPort[1]));
            } else {
                log.info("监测点数据接入(Socket):平台url为空");
                return;
            }
        }, 0, platform.getFrequency(), TimeUnit.SECONDS);

    }

    private JSONObject formatFieldMessage(JSONObject json, MhPlatformField field, Map<String, MonitorPointAPIData> dataMap, List<MhPlatformPoint> ptMornitList, MhPlatform platform) {
        if (MonitPointFieldDataType.DATE.getCode().equalsIgnoreCase(field.getDataType())) {
            if ("Now".equalsIgnoreCase(field.getFixedValue())) {
                json.put(field.getFieldName(), new SimpleDateFormat(field.getFormat()).format(new Date()));
            }
        } else if (MonitPointFieldDataType.STRING.getCode().equalsIgnoreCase(field.getDataType())) {
            json.put(field.getFieldName(), field.getFixedValue());
        } else if (MonitPointFieldDataType.UUID.getCode().equalsIgnoreCase(field.getDataType())) {
            json.put(field.getFieldName(), UUID.randomUUID().toString().replace("-", "").toUpperCase());
        } else if (MonitPointFieldDataType.JSON.getCode().equalsIgnoreCase(field.getDataType())) {
            List<MhPlatformField> fieldList = mhPlatformFieldDao.findByParentId(field.getId());
            JSONObject obj = new JSONObject();
            String encrypt = null;
            for (MhPlatformField f : fieldList) {
                formatFieldMessage(obj, f, dataMap, ptMornitList, platform);
            }
            //加密
            if (platform.getEncryptionType() != null) {
                Optional<BaseTypeGroupItem> etp = baseTypeGroupItemDao.findById(platform.getEncryptionType());
                if (etp.get().getName().equalsIgnoreCase("AES")) {
                    encrypt = MhAesUtil.encrypt(obj.toJSONString(), platform.getPassword(), platform.getAccount());
                    String decrypt = MhAesUtil.decrypt(encrypt, platform.getPassword(), platform.getAccount());
                    log.info(".........解密文本:{}", decrypt);
                }
                json.put(field.getFieldName(), encrypt);
            } else {
                encrypt = obj.toString();
                json.put(field.getFieldName(), JSON.parseObject(encrypt));
            }

        } else if (MonitPointFieldDataType.LIST.getCode().equalsIgnoreCase(field.getDataType())) {
            JSONObject aryObj = null;
            JSONArray array = new JSONArray();
            List<MhPlatformField> fieldList = mhPlatformFieldDao.findByParentId(field.getId());
            for (MhPlatformPoint ptPoint : ptMornitList) {
                aryObj = new JSONObject();
                MonitorPointAPIData pointData = dataMap.get(ptPoint.getPointCode());
                if (pointData == null) {
                    continue;
                }
                //获取监测点平台对应编号/名称
                MhPlatformPoint mhPoint = mhPlatformPointDao.findByPointCode(ptPoint.getPointCode());
                if (mhPoint != null) {
                    for (MhPlatformField f : fieldList) {
                        // 映射字段
                        if (StringUtils.isNotEmpty(f.getMapFieldName())) {
                            BeanWrapper bw = new BeanWrapperImpl(pointData);
                            if ("tagName".equalsIgnoreCase(f.getMapFieldName()) && mhPoint.getCodeOrName() != null) {
                                aryObj.put(f.getFieldName(), mhPoint.getCodeOrName());
                            } else {
                                aryObj.put(f.getFieldName(), bw.getPropertyValue(f.getMapFieldName()));
                            }
                        } else {
                            aryObj.put(f.getFieldName(), f.getFixedValue());
                        }
                    }
                }
                array.add(aryObj);
            }
            json.put(field.getFieldName(), array);
        }
        return json;
    }

    //获取socketMessage
    private String getSocketMessage(MhPlatform platform, List<MhPlatformPoint> pointList) {
        //查询监测点检测数据
        List<String> collect = pointList.stream().filter(r -> r.getPointCode() != null)
                .map(r -> r.getPointCode()).collect(Collectors.toList());
        List<MonitorPointAPIData> dataList = getMonitorPointAPIData(collect);
        log.info("读取的原数据 dataList.............." + dataList);
        Map<String, MonitorPointAPIData> dataMap = new HashMap<>();
        if (dataList != null) {
            for (MonitorPointAPIData data : dataList) {
                dataMap.put(data.getTagName(), data);
            }
        }
        //平台字段配置列表
        List<MhPlatformField> fieldList = mhPlatformFieldDao.findByPlatformIdAndParentIdIsNull(platform.getId());
        JSONObject jsonObj = new JSONObject();
        for (MhPlatformField f : fieldList) {
            jsonObj = formatFieldMessage(jsonObj, f, dataMap, pointList, platform);
        }
        String message = new StringBuffer(jsonObj.toJSONString()).append("@@").toString();
        return message;
    }


    private List<MonitorPointAPIData> getMonitorPointAPIData(List<String> collect) {
        Date now = new Date();
        long time = 5 * 60 * 1000;//5分钟  系统时间前后5分钟
        Date from = new Date(now.getTime() - time);
        Date to = new Date(now.getTime() + time);
        return monitorPointDataAPIDao.findByTagNameInAndTagTimeBetween(collect, from, to);
    }

    //socket 传输数据
    private void transforDataBySocket(String message, String address, Integer port) {
        MhWebSocketClientInstance.getWebSocketClientAndSend(message, "true", address, port);
        log.info("监测点数据接入(Socket):End................");
    }

    @PreDestroy
    public void closeTaskJdbc() {
        if (!taskScheduler.isShutdown()) {
            taskScheduler.shutdownNow();
        }
    }


}
